package cn.edu.nju.ws.sview.reasoning.test;


import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;

import cn.edu.nju.ws.sview.crawler.Crawler;
import cn.edu.nju.ws.sview.rdf.RDFFactory;
import cn.edu.nju.ws.sview.rdf.ResourceFactory;
import cn.edu.nju.ws.sview.rdf.URIResource;
import cn.edu.nju.ws.sview.reasoning.Atom;
import cn.edu.nju.ws.sview.reasoning.Constant;
import cn.edu.nju.ws.sview.reasoning.GroundAtom;
import cn.edu.nju.ws.sview.reasoning.KnowledgeBase;
import cn.edu.nju.ws.sview.reasoning.Predicate;
import cn.edu.nju.ws.sview.reasoning.ProductionMemory;
import cn.edu.nju.ws.sview.reasoning.Repository;
import cn.edu.nju.ws.sview.reasoning.Rule;
import cn.edu.nju.ws.sview.reasoning.Term;
import cn.edu.nju.ws.sview.reasoning.Variable;
import cn.edu.nju.ws.sview.reasoning.WorkingMemory;
import cn.edu.nju.ws.sview.reasoning.provenance.FromSchemaReasoning;
import cn.edu.nju.ws.sview.reasoning.provenance.FromDataMembers;
import cn.edu.nju.ws.sview.reasoning.provenance.ProvenanceFactory;

import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.vocabulary.RDF;

public class test2 {
	//type = 0 constant, type = 1 variable
	public static Atom<Term> createAtom(int arity,String predSymbol,int[] types,String[] values) throws SQLException{
		Predicate predicate = new Predicate(ResourceFactory.getInstance().createURIResource("test2/"+predSymbol),arity);
		ArrayList<Term> list = new ArrayList<Term>();
		for(int i=0;i<arity;i++){
			String value = values[i];
			Term term;
			if(types[i]==0){
				 term = new Constant(ResourceFactory.getInstance().createURIResource("test2/"+value));
			}else{
				term = new Variable(value) ;
			}
			list.add(term) ;
		}
		Atom<Term> atom = new Atom<Term>(predicate,list);
		return atom;
	}
	
   
    public static void main(String[] args) throws SQLException{
    	Crawler.getInstance().exit();
    	OntModel model = ModelFactory.createOntologyModel();	
    	//Facts   p('a0').p('a1').p('a2').p('a3').p('a4').p('a5').p('a6').p('a7').p('a8').p('a9').p('a10').
    	String[] fObject = new String[40] ;
    	String[] fSubject = new String[40] ;
    	for(int i=0;i<40;i++){
    		fObject[i] = "test2/p" ;
    		String a = "test2/a"+i;
    		fSubject[i] =a;
    	}
    	HashSet<GroundAtom> facts = new HashSet<GroundAtom>();
    	for(int i = 0;i<40;i++){
    	    URIResource pred = ResourceFactory.getInstance().createURIResource(fObject[i]);
    	    URIResource arg =  ResourceFactory.getInstance().createURIResource(fSubject[i]);
    	    Constant s = new Constant(arg);
    	    ArrayList<Constant> list = new ArrayList<Constant>();
    	    list.add(s) ;
    	    Predicate predicate = new Predicate(pred,1);
    	    GroundAtom fact = new GroundAtom(predicate,list,ProvenanceFactory.getInstance().createProvFromDataMembers());
    	    facts.add(fact);
    	}
    	
    	long start = 0;
    	for(int kk=0;kk<1;kk++){
       		if(kk==1)
       			start = System.currentTimeMillis();
        	WorkingMemory wm =new WorkingMemory();
        	ProductionMemory pm = new ProductionMemory();
    	//rules   ra(?A,?B):-p(?A),p(?B).  rb(?A,?B):-p(?A),p(?B). r(?A,?B):-ra(?A,?B),rb(?A,?B). q(?A):-r(?A,?B).  q(?B):-r(?A,?B).   
    	 ArrayList<Atom<Term>> bodyList1 = new ArrayList<Atom<Term>>();
    	     int[] types = {1,1};
    	     String[] values = {"A","B"};
    	     Atom<Term> headAtom1 = createAtom(2,"r",types,values);    
    	     String[][] bvalues = {{"A","B"},{"A","B"}};
    	     String[] preds = {"ra","rb"};
    	     for(int i=0;i<2;i++){
    	     		Atom<Term> atom = createAtom(2,preds[i],types,bvalues[i]);
    	     		bodyList1.add(atom);
    	     }
    	     Rule rule1 = new  Rule(headAtom1,bodyList1,new FromSchemaReasoning());
    	     pm.addRule(rule1) ;
    	   
    	     ArrayList<Atom<Term>> bodyList2 = new ArrayList<Atom<Term>>();
    	     Atom<Term> headAtom2 = createAtom(2,"ra",types,values);   
    	     int[] types2={1}; 
    	     String[][] bvalues2 = {{"A"},{"B"}};
    	     String[] preds2 = {"p","p"};
    	     for(int i=0;i<2;i++){
    	     		Atom<Term> atom = createAtom(1,preds2[i],types2,bvalues2[i]);
    	     		bodyList2.add(atom);
    	     }
    	     Rule rule2 = new  Rule(headAtom2,bodyList2,new FromSchemaReasoning());
    	     pm.addRule(rule2) ;
    	     
    	      Atom<Term> headAtom3 = createAtom(2,"rb",types,values);   
    	      Rule rule3 = new  Rule(headAtom3,bodyList2,new FromSchemaReasoning());
    	     pm.addRule(rule3) ;
    	     
    	     ArrayList<Atom<Term>> bodyList4 = new ArrayList<Atom<Term>>();
    	      String[] values4 = {"A"};
    	     Atom<Term> headAtom4= createAtom(1,"q",types2,values4);   
    	     for(int i=0;i<1;i++){
    	     		Atom<Term> atom = createAtom(2,"r",types,values);
    	     		bodyList4.add(atom);
    	     }
    	     Rule rule4 = new  Rule(headAtom4,bodyList4,new FromSchemaReasoning());
    	     pm.addRule(rule4) ;
    	     
    	      String[] values5 = {"B"};
    	     Atom<Term> headAtom5= createAtom(1,"q",types2,values5);  
    	     Rule rule5 = new  Rule(headAtom5,bodyList4,new FromSchemaReasoning());
    	     pm.addRule(rule5) ;
//    	      System.out.println("[INFO]loading rules completes");
     /**new a knowledge base**/
       KnowledgeBase kb = new KnowledgeBase(wm,pm);
       for(GroundAtom atom:facts){
    	   kb.addFact(atom);
       }
       /*Add a query q(?x)* answer: 'a0'~'a39'*/
       int[] x ={1};
       String[] y = {"x"};
    	Atom<Term> query = createAtom(1,"q",x,y);
	   HashSet<GroundAtom> ans = kb.Evaluate(query,false) ;
	   System.out.println(kb.toString());
//	   kb.Reset();
 	   System.out.println("Query "+query.toString()+"\n");
	   System.out.println("Answer:\n ");
	   for(GroundAtom fact:ans){
		   System.out.println(fact);
	   }
    }
   	  long time = System.currentTimeMillis()-start;
 	  System.out.println("Time: " +time);
    }
}
